/*
    Copyright (C) 2010-2011  Anton Dedkov (Antonded). antonded@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef COMPRESSOR_H
#define COMPRESSOR_H

#include <string>
#include <fstream>
#include <queue>
#include <vector>
#include <QThread>

using std::string;
using std::fstream;
using std::vector;
using std::priority_queue;

//-----------------------------------------------------------------------------

class Compressor: public QThread
{Q_OBJECT
    struct TreeNode;
    
    public:

    Compressor ();
    ~Compressor ();

    void Compress (string in_file, string out_file);
    void Decompress (string in_file, string out_file);
    void Dump () const;
	
	virtual void run ();
    
    struct TreeNodeCompare
    {
        bool operator() (const TreeNode* rnode1, const TreeNode* rnode2);
    };
    
    private:

    void Profile ();
    void BuildTree ();
    void ReadToBuffer (string file);
    void WriteProfile (fstream& fout);
    void WriteCompressed (fstream& fout);
    void WriteDecompressed (fstream& fout);

    void ClearAll ();

    void ReadProfile ();
    
    struct TreeNode
    {
        long long int freq;
        unsigned int symbol;
        
        TreeNode* parent_;
        TreeNode* child_ [2];
    };

    TreeNode* profile_ [257];

    TreeNode* tree_node_buffer_;
    int buffer_index_;

    priority_queue <TreeNode*, vector <TreeNode*>, TreeNodeCompare> current_forest_;

    unsigned char* file_read_buffer_;
    unsigned int file_read_buffer_size_;

    static const int eof_ = 257;
    static const int file_buffer_size_ = 1024;

};

//-----------------------------------------------------------------------------

#endif // COMPRESSOR_H
